-- 2022-8-15

---[[ 17.1.2搜索路径

    -- 在搜索一个Lua文件时 函数require使用的路径与典型的路径略有不同
    -- 典型的路径是很多目录组成的列表 并在其中搜索指定的文件 不过 ISO C(Lua语言依赖的抽象平台)并没有目录的概念
    -- 所以 函数require使用的路径是一组模板(template) 其中的每项都指定了将模块名(函数require的参数)转换为文件名的方式
    -- 更准确的说 这种路径中的每一个模板都是一个包含可选问号的文件名
    -- 对于每个模板 函数require会用模板名来替换每一个问号 然后检查结果是否存在对应的文件 如果不存在 则尝试下一个模板
    -- 路径中的模板以在大多数操作系统中很少被用于文件名的分号隔开 例如考虑如下路径
    -- ?;?.lua;c:\windows\?;/usr/local/lua/?/?.lua
    -- 在使用这个路径的时 调用require "sql"将尝试打开如下的Lua文件:
    -- sql
    -- sql.lua
    -- c:windows\sql
    -- usr/local/lua/sql/sql.lua
    -- 函数require只处理分号(作为分隔符)和问号 所有其他的部分(包括目录分隔符和文件扩展名)则路径自己定义

    -- 函数require用于搜索Lua文件的路径是变量package.path的当前值
    -- 当package模块被初始化后 它就把变量package.path设置成环境变量LUA_PATH_5_3的值
    -- 如果这个环境变量没有定义 那么Lua语言则尝试则使用一个编译时定义的默认路径
    -- 在使用一个环境变量的值时 Lua语言会将其中所有的";;"替换为默认路径
    -- 例如 如果将LUA_PATH_5_3设为"mydir/?.lua;;" 那么最终路径就会是模板"mydir/?.lua"后跟默认路径

    -- 搜索C标准库的路径的逻辑与此相同 只不过C标准库的路径来自变量package.cpath而不是package.path
    -- 类似地 这个变量的初始值也来自环境变量LUA_CPATH_5_3或LUA_CPATH 在POSIX系统在这个路径的典型值形如:
    -- ./?/so;/usr/local/lib/lua/5.2/?.so
    -- 请注意定义文件扩展名的路径 在上例中 所有模板使用的都是.so 而在Windows操作系统中此典型路径通常形如:
    -- .\?.dll;C:\Program Files\Lua502\dll\?.dll

    -- 函数package.searchpath中实现了搜索库的所有规则 该函数的参数包括模块名和路径 然后遵循上述规则来搜索文件
    -- 函数package.searchpath要么返回第一个存在的文件的文件名 要么返回nil外加描述的所有文件都无法成功打开的错误信息 如下:
    -- 看书

    -- 作为一个有趣的练习 我们在示例17.1中实现了一个与函数packege.searchpath类似的函数
    -- 看书

    -- 上述函数首先替换目录分隔符 在本例中即把所有的点换成斜杠(我们会在后续看到模块名中的点具有特殊含义)
    -- 之后 该函数遍历路径中的所有组成部分 也就是每一个不含分号的最长匹配
    -- 对于每一个组成部分 该函数使用模块名来替换问号得到最终的文件名 然后检查相应的文件是否存在
    -- 如果存在 该函数关闭这个文件 然后返回文件的名称 否则 该函数保存失败的文件名用于可能的错误提示
    -- (请注意字符串缓冲区在避免创建无用的长字符串时的作用) 如果一个文件都找不到 该函数则返回nil及最终的错误信息
--]]